package com.woniu.stafforder.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.common.constant.OrderStatusConstant;
import com.woniu.common.dto.OrderDetailDto;
import com.woniu.common.dto.SkuDto;
import com.woniu.common.feignClient.ProductFeignClient;
import com.woniu.common.util.ResponseData;
import com.woniu.stafforder.dto.ChangeChildrenOrderStateDto;
import com.woniu.stafforder.dto.ExpressDto;
import com.woniu.stafforder.dto.OrderMainDto;
import com.woniu.stafforder.entity.Order;
import com.woniu.stafforder.entity.OrderExpress;
import com.woniu.stafforder.entity.OrderExpressLocation;
import com.woniu.stafforder.entity.Point;
import com.woniu.stafforder.service.OrderDetailService;
import com.woniu.stafforder.service.OrderExpressLocationService;
import com.woniu.stafforder.service.OrderExpressService;
import com.woniu.stafforder.mapper.OrderExpressMapper;
import com.woniu.stafforder.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @author Administrator
 * @description 针对表【t_order_express(订单物流)】的数据库操作Service实现
 * @createDate 2024-05-28 13:13:49
 */
@Service
public class OrderExpressServiceImpl extends ServiceImpl<OrderExpressMapper, OrderExpress>
        implements OrderExpressService {
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderExpressLocationService orderExpressLocationService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    private static final String REDIS_ORDER_MAIN_DTO = "orderMainDto:";
    private static final String REDIS_EXPRESS_DTO = "expressDto:";
    private static final String REDIS_ORDER_EXPRESS_DTO = "orderExpressDto:";
    private static final String REDIS_EXPRESS_LOCATION = "expressLocation:";
    private static final String REDIS_CURRENT_LOCATION = "currentLocation:";

    /**
     * 发货
     *
     * @param orderNum
     * @return
     */
    @Override
    public ResponseData<?> addExpress(Long orderNum) {
        ResponseData<?> responseData = orderService.queryOrderByOrderNum(orderNum);
        OrderMainDto orderMainDto = (OrderMainDto) responseData.getData();

        Integer status = orderMainDto.getStatus();
        if (status.equals(OrderStatusConstant.WAIT_SEND.getCode())) {
            List<Long> childIdList = orderMainDto.getIdList();

            childIdList.forEach(id -> {
                OrderExpress orderExpress = new OrderExpress();
                orderExpress.setCompanyName("东风快递");
                orderExpress.setCompanyCode("DFO");
                long l = IdUtil.getSnowflake(1, 1).nextId();
                String string = Long.toString(l);
                String codeString = string.substring(3, 15);
                orderExpress.setExpressCode("DF" + codeString);

                OrderDetailDto orderDetailDto = orderDetailService.queryOrderDetailById(id);
                SkuDto skuDto = productFeignClient.querySkuType(orderDetailDto.getItemId().longValue());
                orderExpress.setStartProvince(skuDto.getProvince());
                orderExpress.setStartPlace(skuDto.getPlace());
                orderExpress.setStartArea(skuDto.getArea());
                orderExpress.setStartAddr(skuDto.getAddr());
                orderExpress.setEndProvince(orderMainDto.getProvince());
                orderExpress.setEndPlace(orderMainDto.getPlace());
                orderExpress.setEndArea(orderMainDto.getArea());
                orderExpress.setEndAddr(orderMainDto.getAddr());
                orderExpress.setOrderDetailId(orderNum);
                save(orderExpress);
            });

            Order order = new Order();
            order.setID(orderNum);
            order.setStatus(OrderStatusConstant.WAIT_RECEIVE.getCode());
            orderService.updateOrderStatus(order);

            ChangeChildrenOrderStateDto changeChildrenOrderStateDto = new ChangeChildrenOrderStateDto();
            changeChildrenOrderStateDto.setIdList(childIdList);
            changeChildrenOrderStateDto.setStatus(OrderStatusConstant.WAIT_RECEIVE.getCode());
            orderDetailService.updateChildrenOrderStatus(changeChildrenOrderStateDto);
            return new ResponseData<>().ok();
        }
        return new ResponseData<>().fail("未支付");
    }

    @Override
    public ResponseData<?> queryExpress(Long orderNum) {
        OrderExpress orderExpress = lambdaQuery().eq(OrderExpress::getOrderDetailId, orderNum).one();
        ExpressDto expressDto = new ExpressDto();
        expressDto.setCompanyName(orderExpress.getCompanyName());
        expressDto.setExpressCode(orderExpress.getExpressCode());

        StringBuilder startLocation = new StringBuilder();
        startLocation.append(orderExpress.getStartPlace());
        startLocation.append(orderExpress.getStartArea());
        startLocation.append(orderExpress.getStartAddr());
        expressDto.setStartLocation(startLocation.toString());

        StringBuilder endLocation = new StringBuilder();
        endLocation.append(orderExpress.getEndPlace());
        endLocation.append(orderExpress.getEndArea());
        endLocation.append(orderExpress.getEndAddr());
        expressDto.setEndLocation(endLocation.toString());
        return new ResponseData<>().ok(expressDto);
    }

    /**
     * 添加经纬度到redis
     *
     * @param expressDto
     * @return
     */
    @Override
    public ResponseData<?> addExpressPoint(ExpressDto expressDto) {
        List<Point> pointList = expressDto.getPointList();
        String expressCode = expressDto.getExpressCode();

        if (redisTemplate.hasKey(REDIS_EXPRESS_LOCATION + expressCode)) {
            return new ResponseData<>().ok();
        }

        OrderExpressLocation orderExpressLocation = new OrderExpressLocation();
        orderExpressLocation.setExpressCode(expressCode);
        for (int i = 0; i < pointList.size(); i++) {
            orderExpressLocation.setLng(pointList.get(i).getLng());
            orderExpressLocation.setLat(pointList.get(i).getLat());
            redisTemplate.opsForHash().putIfAbsent(REDIS_EXPRESS_LOCATION + expressCode, String.valueOf(i), orderExpressLocation);
        }
        Thread thread = new Thread(() -> {
            int i = 0;
            while (i < pointList.size()) {
                try {
                    OrderExpressLocation orderExpressLocation1 = (OrderExpressLocation) redisTemplate.opsForHash().get(REDIS_EXPRESS_LOCATION + expressCode, String.valueOf(i));
                    if (ObjectUtil.isNotEmpty(orderExpressLocation1)) {
                        List<Double> list = new ArrayList<>(2);
                        list.add(orderExpressLocation1.getLng());
                        list.add(orderExpressLocation1.getLat());
                        redisTemplate.opsForValue().set(REDIS_CURRENT_LOCATION + expressCode, list);
                    }
                    i++;
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        return new ResponseData<>().ok();
    }

    @Override
    public ResponseData<?> getExpressPoint(String expressCode) {
        List<Double> doubles = (List<Double>) redisTemplate.opsForValue().get(REDIS_CURRENT_LOCATION + expressCode);
        return new ResponseData<>().ok(doubles);
    }
}




